package com.sywl.ytcx.service.Impl;

import com.sywl.ytcx.config.OrderExcelDTO;
import com.sywl.ytcx.config.OverallViewOrderRateVO;
import com.sywl.ytcx.config.PostViewOrderRateVO;
import com.sywl.ytcx.config.UserPostViewOrderRateVO;
import com.sywl.ytcx.entity.order.Order;
import com.sywl.ytcx.entity.res.ResponseResult;
import com.sywl.ytcx.entity.user.User;
import com.sywl.ytcx.mapper.OrderListMapper;
import com.sywl.ytcx.mapper.UserMapper;
import com.sywl.ytcx.service.OrderListService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单列表服务实现类：实现 OrderListService 接口中定义的所有业务方法。
 * 包括订单查询、导出、收入统计、按日期筛选等。
 */
@Service
@Slf4j
public class OrderListServiceImpl implements OrderListService {

    private final OrderListMapper orderListMapper;

    private final UserMapper userMapper;

    // 支持的排序顺序列表，仅允许 "asc" 和 "desc"
    private static final List<String> ALLOWED_ORDERS = Arrays.asList("asc", "desc");

    // 定义日期格式化器：仅日期
    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    // 定义日期时间格式化器：精确到秒
    private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 构造函数，使用 Spring 自动注入 Mapper
     * @param orderListMapper 注入订单数据访问对象
     * @param userMapper 注入用户数据访问对象，用于账号校验
     */
    @Autowired
    public OrderListServiceImpl(OrderListMapper orderListMapper, UserMapper userMapper) {
        this.orderListMapper = orderListMapper;
        this.userMapper = userMapper;
    }

    /**
     * 查询所有待支付订单列表
     * @return 待支付订单集合
     */
    @Override
    public List<Order> listPendingPayment() {
        return orderListMapper.findPendingPayment();
    }

    /**
     * 查询所有已支付订单列表
     * @return 已支付订单集合
     */
    @Override
    public List<Order> listPaid() {
        return orderListMapper.findPaid();
    }

    /**
     * 查询所有待出稿订单列表
     * @return 待出稿订单集合
     */
    @Override
    public List<Order> listUnpublished() {
        return orderListMapper.findUnpublished();
    }

    /**
     * 查询所有已出稿订单列表
     * @return 已出稿订单集合
     */
    @Override
    public List<Order> listPublished() {
        return orderListMapper.findPublished();
    }

    /**
     * 根据用户 ID 查询订单列表，先校验用户是否存在
     * @param userId 用户 ID
     * @return 该用户的订单集合
     */
    @Override
    public ResponseResult listByUserId(int userId) {
        // 1. 判断用户是否存在
        User user = userMapper.selectUserById(userId);
        if (user == null) {
            // 2. 用户不存在时，抛出异常或返回空列表
            return new ResponseResult("OL400", "用户不存在", null);
        }
        // 3. 用户存在，正常查询
        List<Order> byUserId = orderListMapper.findByUserId(userId);

        return new ResponseResult(200, "按用户ID查询订单成功", byUserId);
    }

    /**
     * 获取所有订单并按创建时间排序
     * @param sortOrder 排序顺序：asc 或 desc
     * @return 包含状态码、消息、以及排序后的订单列表的响应
     */
    @Override
    public ResponseResult listAllByCreatedAt(String sortOrder) {
        try {
            // 校验并标准化排序顺序，返回 "asc" 或 "desc"
            String order = validateOrder(sortOrder);
            // 根据创建时间调用 Mapper 查询
            List<Order> list = orderListMapper.findAllByCreatedAt(order);
            // 如果返回结果为空，则提示无数据
            if (CollectionUtils.isEmpty(list)) {
                return new ResponseResult("OL400", "无订单数据（按创建时间）", Collections.emptyList());
            }
            // 正常返回查询结果
            return new ResponseResult("200", "获取订单列表（按创建时间）成功", list);
        } catch (IllegalArgumentException ex) {
            // 捕获排序参数校验异常，返回错误消息
            return new ResponseResult("OL400", ex.getMessage(), null);
        } catch (Exception ex) {
            // 捕获其他运行时异常，记录日志并返回通用错误
            log.error("listAllByCreatedAt 异常", ex);
            return new ResponseResult("OL400", "服务器内部错误", null);
        }
    }

    /**
     * 获取所有订单并按总金额排序
     * @param sortOrder 排序顺序：asc 或 desc
     * @return 包含状态码、消息、以及排序后的订单列表的响应
     */
    @Override
    public ResponseResult listAllByTotalAmount(String sortOrder) {
        try {
            String order = validateOrder(sortOrder); // 校验排序顺序
            List<Order> list = orderListMapper.findAllByTotalAmount(order); // 查询
            if (CollectionUtils.isEmpty(list)) {
                return new ResponseResult("OL400", "无订单数据（按订单金额）", Collections.emptyList());
            }
            return new ResponseResult("200", "获取订单列表（按订单金额）成功", list);
        } catch (IllegalArgumentException ex) {
            return new ResponseResult("OL400", ex.getMessage(), null);
        } catch (Exception ex) {
            log.error("listAllByTotalAmount 异常", ex);
            return new ResponseResult("OL500", "服务器内部错误", null);
        }
    }

    /**
     * 校验排序顺序，仅允许 "asc" 或 "desc"，默认返回 "desc"
     * @param sortOrder 原始排序参数
     * @return 标准化后的排序顺序
     * @throws IllegalArgumentException 如果排序参数非法
     */
    private String validateOrder(String sortOrder) {
        if (sortOrder == null || sortOrder.trim().isEmpty()) {
            return "desc"; // 默认降序
        }
        String order = sortOrder.trim().toLowerCase(); // 标准化
        if (!ALLOWED_ORDERS.contains(order)) {
            throw new IllegalArgumentException("不支持的排序顺序: " + sortOrder);
        }
        return order;
    }

    /**
     * 根据订单编号查询单个订单
     * @param orderNumber 订单编号
     * @return 包含订单对象的响应，如果不存在则返回 404
     */
    @Override
    public ResponseResult getByOrderNumber(String orderNumber) {
        // 如果订单编号为空，返回错误
        if (orderNumber == null || orderNumber.trim().isEmpty()) {
            return new ResponseResult("OL400", "订单号不能为空", null);
        }
        Order order = orderListMapper.findByOrderNumber(orderNumber.trim()); // 查询
        // 如果订单不存在，返回错误
        if (order == null) {
            return new ResponseResult("OL400", "订单不存在", null);
        }
        return new ResponseResult("200", "获取订单成功", order);
    }

    /**
     * 根据订单 ID 查询单个订单
     * @param orderId 订单 ID
     * @return 包含订单对象的响应，如果不存在则返回 404
     */
    @Override
    public ResponseResult getById(Long orderId) {
        // 如果orderId为空或小于等于0，返回错误
        if (orderId == null || orderId <= 0) {
            return new ResponseResult("OL400", "orderId 参数非法", null);
        }
        Order order = orderListMapper.findById(orderId); // 查询
        // 如果订单不存在，返回错误
        if (order == null) {
            return new ResponseResult("OL400", "订单未找到: " + orderId, null);
        }
        return new ResponseResult("200", "查询成功", order);
    }

    /**
     * @param o 订单实体
     * @return 填充好的导出 DTO
     */
    private OrderExcelDTO toExcelDTO(Order o) {
        OrderExcelDTO dto = new OrderExcelDTO(); // 新建 DTO 对象
        dto.setOrderId(Long.valueOf(o.getOrder_id())); // 转换类型
        dto.setUserId(o.getUser_id());                // 设置用户 ID
        dto.setOrderNumber(o.getOrder_number());       // 设置订单编号
        dto.setTotalAmount(BigDecimal.valueOf(o.getTotal_amount())); // 设置金额
        dto.setStatus(o.getStatus());                  // 设置状态
        dto.setCreatedAt(o.getCreated_at());           // 设置创建时间
        dto.setPaymentTime(o.getPayment_time());       // 设置支付时间
        dto.setShippingAddress(o.getShipping_address()); // 设置收货地址
        return dto; // 返回 DTO
    }

    /**
     * 获取所有订单的导出数据列表
     */
    @Override
    public List<OrderExcelDTO> getAllForExport() {
        return orderListMapper.findAll() // 查询所有订单
                .stream()                  // 转为 Stream
                .map(this::toExcelDTO)    // 映射为 DTO
                .collect(Collectors.toList()); // 收集
    }

    /**
     * 根据用户 ID 获取导出数据列表
     */
    @Override
    public List<OrderExcelDTO> getByUserForExport(Integer userId) {
        return orderListMapper.findByUserId(userId)// 查询指定用户
                .stream()
                .map(this::toExcelDTO)// 映射为 DTO
                .collect(Collectors.toList());
    }

    /**
     * 根据账号查询订单列表，先校验账号是否存在
     */
    @Override
    public ResponseResult listOrdersByAccount(String account) {
        if (account == null || account.trim().isEmpty()) {
            return new ResponseResult("OL400", "账号不能为空", null);
        }
        int count = userMapper.countAccount(account.trim()); // 校验账号
        if (count == 0) {
            return new ResponseResult("OL400", "账号不存在", null);
        }
        List<Order> list = orderListMapper.findByAccount(account.trim()); // 查询
        return new ResponseResult("200", "查询成功", list);
    }

    /**
     * 获取指定用户的订单列表
     */
    @Override
    public ResponseResult getOrdersByUserId(int userId) {
        try {
            List<Order> orders = orderListMapper.selectByUserId(userId); // 查询
            if (CollectionUtils.isEmpty(orders)) {
                return new ResponseResult("OL400", "该用户暂无订单", null);
            }
            return new ResponseResult("200", "订单查询成功", orders);
        } catch (Exception e) {
            log.error("getOrdersByUserId 异常", e);
            return new ResponseResult("OL500", "查询订单失败: " + e.getMessage(), null);
        }
    }

    /**
     * 按日期降序查询用户订单
     */
    @Override
    public ResponseResult getOrdersByDate(int userId) {
        try {
            List<Order> orders = orderListMapper.selectOrdersByDateDesc(userId); // 查询
            if (CollectionUtils.isEmpty(orders)) {
                return new ResponseResult("200", "暂无订单数据", null);
            }
            return new ResponseResult("200", "查询成功", orders);
        } catch (Exception e) {
            log.error("getOrdersByDate 异常", e);
            return new ResponseResult("OL400", "按日期查询订单失败", null);
        }
    }

    /**
     * 查询用户未付款订单
     */
    @Override
    public ResponseResult getUnpaidOrders(int userId) {
        try {
            List<Order> orders = orderListMapper.selectUnpaidOrders(userId);
            if (CollectionUtils.isEmpty(orders)) {
                return new ResponseResult("200", "暂无待付款订单", null);
            }
            return new ResponseResult("200", "查询成功", orders);
        } catch (Exception e) {
            log.error("getUnpaidOrders 异常", e);
            return new ResponseResult("OL400", "按未付款查询订单失败", null);
        }
    }

    /**
     * 查询用户已付款订单
     */
    @Override
    public ResponseResult getPaidOrders(int userId) {
        try {
            List<Order> orders = orderListMapper.selectPaidOrders(userId);
            if (CollectionUtils.isEmpty(orders)) {
                return new ResponseResult("200", "暂无已付款订单", null);
            }
            return new ResponseResult("200", "查询成功", orders);
        } catch (Exception e) {
            log.error("getPaidOrders 异常", e);
            return new ResponseResult("OL400", "按已付款查询订单失败", null);
        }
    }

    /**
     * 统计今日收入
     * 注：使用服务器当前时间，时间范围从当日 00:00:00 到当前时刻
     */
    @Override
    public ResponseResult getDailyIncome() {
        try {
            LocalDateTime start = LocalDate.now().atStartOfDay(); // 获取今天零点
            LocalDateTime end = LocalDateTime.now();             // 当前时间
            BigDecimal total = orderListMapper.sumAmountBetween(null, start, end); // 汇总金额
            return new ResponseResult("200", "获取今日收入成功", total);
        } catch (Exception e) {
            log.error("getDailyIncome 异常", e);
            return new ResponseResult("OL400", "计算今日收入失败: " + e.getMessage(), null);
        }
    }

    /**
     * 统计本月收入
     * 时间范围从当月 1 日 00:00:00 到当前时刻
     */
    @Override
    public ResponseResult getMonthlyIncome() {
        try {
            LocalDateTime start = YearMonth.now().atDay(1).atStartOfDay(); // 本月第一天零点
            LocalDateTime end = LocalDateTime.now();                      // 当前时刻
            BigDecimal total = orderListMapper.sumAmountBetween(null, start, end);
            return new ResponseResult("200", "获取本月收入成功", total);
        } catch (Exception e) {
            log.error("getMonthlyIncome 异常", e);
            return new ResponseResult("OL400", "计算本月收入失败: " + e.getMessage(), null);
        }
    }

    /**
     * 按下单时间范围筛选订单
     * @param dateStart 支持 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss
     * @param dateEnd   支持 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss
     * @return 筛选结果列表
     */
    @Override
    public ResponseResult listByDateRange(String dateStart, String dateEnd) {
        try {
            LocalDateTime start = parseAndValidateDate(dateStart, "开始"); // 解析并校验
            LocalDateTime end = parseAndValidateDate(dateEnd, "结束");     // 解析并校验
            if (start.isAfter(end)) {
                return new ResponseResult("OL400", "开始时间不能晚于结束时间", null);
            }
            List<Order> list = orderListMapper.selectByDateRange(start, end); // 查询
            return new ResponseResult("200", "按日期范围筛选订单列表成功", list);
        }catch (Exception e) {
            log.error("listByDateRange 异常", e);
            return new ResponseResult("OL400", "按日期范围筛选订单列表失败: " + e.getMessage(), null);
        }
    }

    /**
     * 解析并校验日期字符串，支持两种格式；同时校验不能晚于当前时间
     * @param text  日期文本
     * @param label 用于错误提示的标签，比如 “开始” 或 “结束”
     * @return 解析后的 LocalDateTime
     * @throws RuntimeException 校验失败时抛出，message 会被直接返回给前端
     */
    private LocalDateTime parseAndValidateDate(String text, String label) {
        if (text == null || text.trim().isEmpty()) {
            throw new RuntimeException(label + "时间不能为空");
        }
        try {
            text = text.trim();
            LocalDateTime dt;
            if (text.length() == 10) {
                dt = LocalDate.parse(text, DATE_FMT).atStartOfDay();
            } else {
                dt = LocalDateTime.parse(text, DATETIME_FMT);
            }
            // 无论是开始还是结束，都不能超过当前时间
            if (dt.isAfter(LocalDateTime.now())) {
                throw new RuntimeException(label + "时间不能晚于当前时间");
            }
            return dt;
        } catch (RuntimeException re) {
            // 如果是我们自己抛出的，就继续往外抛
            throw re;
        } catch (Exception e) {
            throw new RuntimeException(label + "时间格式错误");
        }
    }


    /**
     * 统计指定用户今日收入
     */
    @Override
    public ResponseResult getUserDailyIncome(int userId) {
        try {
            LocalDateTime start = LocalDate.now().atStartOfDay();
            LocalDateTime end = LocalDateTime.now();
            BigDecimal total = orderListMapper.sumAmountBetween(userId, start, end);
            return new ResponseResult("200", "获取用户今日收入成功", total);
        } catch (Exception e) {
            log.error("getUserDailyIncome 异常", e);
            return new ResponseResult("OL400", "获取用户今日收入失败: " + e.getMessage(), null);
        }
    }

    /**
     * 统计指定用户本月收入
     */
    @Override
    public ResponseResult getUserMonthlyIncome(int userId) {
        try {
            LocalDateTime start = YearMonth.now().atDay(1).atStartOfDay();
            LocalDateTime end = LocalDateTime.now();
            BigDecimal total = orderListMapper.sumAmountBetween(userId, start, end);
            return new ResponseResult("200", "获取用户本月收入成功", total);
        } catch (Exception e) {
            log.error("getUserMonthlyIncome 异常", e);
            return new ResponseResult("OL400", "获取用户本月收入失败: " + e.getMessage(), null);
        }
    }

    /**
     * 查询所有退款订单
     */
    @Override
    public ResponseResult getCancelledOrders() {
        try {
            List<Order> list = orderListMapper.findCancelled();
            return new ResponseResult("200", "查询所有退款订单成功", list);
        } catch (Exception e) {
            log.error("getCancelledOrders 异常", e);
            return new ResponseResult("OL400", "查询所有退款订单失败: " + e.getMessage(), null);
        }
    }

    /**
     * 按日期查询取消(退款)订单，支持格式校验和顺序校验
     */
    @Override
    public ResponseResult getCancelledOrdersByDate(String dateStart, String dateEnd) {
        try {
            LocalDateTime start = parseAndValidateDate(dateStart, "开始");
            LocalDateTime end = parseAndValidateDate(dateEnd, "结束");
            if (start.isAfter(end)) {
                return new ResponseResult("OL400", "开始时间不能晚于结束时间", null);
            }
            List<Order> list = orderListMapper.findCancelledByDate(start, end);
            return new ResponseResult("200", "按日期查询退款订单成功", list);
        }catch (Exception e) {
            log.error("getCancelledOrdersByDate 异常", e);
            return new ResponseResult("OL400", "按日期查询退款订单失败: " + e.getMessage(), null);
        }
    }

    /**
     * 查询指定用户的取消(退款)订单
     */
    @Override
    public ResponseResult getUserCancelledOrders(int userId) {
        try {
            List<Order> list = orderListMapper.findCancelledByUser(userId);
            return new ResponseResult("200", "查询用户退款订单成功", list);
        } catch (Exception e) {
            log.error("getUserCancelledOrders 异常", e);
            return new ResponseResult("OL400", "查询用户退款订单失败: " + e.getMessage(), null);
        }
    }

    /**
     * 按日期查询指定用户的取消(退款)订单
     */
    @Override
    public ResponseResult getUserCancelledOrdersByDate(int userId, String dateStart, String dateEnd) {
        try {
            LocalDateTime start = parseAndValidateDate(dateStart, "开始");
            LocalDateTime end = parseAndValidateDate(dateEnd, "结束");
            if (start.isAfter(end)) {
                return new ResponseResult("OL400", "开始时间不能晚于结束时间", null);
            }
            List<Order> list = orderListMapper.findCancelledByUserAndDate(userId, start, end);
            return new ResponseResult("200", "按日期查询用户退款订单成功", list);
        }catch (Exception e) {
            log.error("getUserCancelledOrdersByDate 异常", e);
            return new ResponseResult("OL400", "按日期查询用户退款订单失败: " + e.getMessage(), null);
        }
    }


    /**
     * 获取帖子转化率
     */
    @Override
    public ResponseResult getPostViewOrderRates() {
        try {
            List<PostViewOrderRateVO> list = orderListMapper.selectPostViewOrderRates();
            return new ResponseResult(
                    "200",
                    list.isEmpty() ? "无数据" : "获取帖子转化率成功",
                    list
            );
        } catch (Exception e) {
            log.error("获取帖子转化率失败", e);
            return new ResponseResult(
                    "OL400",
                    "服务器错误: 获取帖子转化率失败",
                    null
            );
        }
    }

    /**
     * 获取全站转化率
     **/
    @Override
    public ResponseResult getOverallViewOrderRate() {
        try {
            OverallViewOrderRateVO vo = orderListMapper.selectOverallViewOrderRate();
            return new ResponseResult(
                    "200",
                    vo == null ? "无数据" : "获取整体转化率成功",
                    vo
            );
        } catch (Exception e) {
            log.error("获取全站转化率失败", e);
            return new ResponseResult(
                    "OL400",
                    "服务器错误: 获取全站转化率失败",
                    null
            );
        }
    }


    @Override
    public ResponseResult getUserPostViewOrderRate(int userId) {
        try {
            // 从视图中查询用户转化率
            UserPostViewOrderRateVO vo = orderListMapper.selectUserPostViewOrderRate(userId);
            if (vo == null) {
                return new ResponseResult("OL400", "未找到用户转化率数据", null);
            }
            return new ResponseResult("200", "获取用户转化率成功", vo);
        } catch (Exception e) {
            log.error("获取用户转化率失败", e);
            return new ResponseResult("OL400", "服务器错误: 获取用户转化率失败", null);
        }
    }
}
